/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.brain.core.manager;

import com.brain.core.common.UtilCore;
import com.brain.core.configuracion.WebServletContextListener;
import com.brain.core.dto.EmpresaDto;
import com.brain.core.dto.ParametroDto;
import com.brain.core.exception.DAOException;
import com.brain.core.view.mbean.ApplicationMBean;

import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpServletResponse;
import jxl.CellView;
import jxl.Workbook;
import jxl.format.*;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import net.sf.jasperreports.engine.*;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.*;
import javax.annotation.Resource;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletOutputStream;
import javax.sql.DataSource;

/**
 *
 * @author Indra
 */
@Service
public class RecursosManager implements Serializable {

    private static Logger logger = Logger.getLogger(RecursosManager.class);
    @Resource
    private ParametroManager parametroManager;

    public DataSource obtenerDataSource() throws NamingException {
        ApplicationMBean applicationMBean = (ApplicationMBean) WebServletContextListener.getApplicationContext().getBean("applicationMBean");
        InitialContext initctx = new InitialContext();
        DataSource ds = (DataSource) initctx.lookup(applicationMBean.getDataSourceName());

        return ds;
    }

    public Connection obtenerConexionDataBase() {

        Connection cnx = null;
        try {
            DataSource ds = obtenerDataSource();
            cnx = ds.getConnection();
        } catch (Exception e) {
            cnx = null;
            logger.error(e);
        }

        return cnx;
    }

    public void cargarInformacionBaseDatos() throws NamingException, SQLException {
        Connection cnx = obtenerConexionDataBase();
        ApplicationMBean applicationMBean = (ApplicationMBean) WebServletContextListener.getApplicationContext().getBean("applicationMBean");
        DatabaseMetaData md = cnx.getMetaData();
        applicationMBean.setDbMotor(md.getDatabaseProductName());
        applicationMBean.setDbMotorVersion(md.getDatabaseProductVersion());
        applicationMBean.setDbDriverName(md.getDriverName() + " " + md.getDriverVersion());
        applicationMBean.setDbUrlConexion(md.getURL());
        applicationMBean.setDbUserName(md.getUserName());


    }

    public String construirTitulo(final String keyEntidad, final int accion, final String... otros) {
        String retorno = null;
        StringBuilder sbTitulo = new StringBuilder();

        ApplicationMBean applicationMBean = (ApplicationMBean) WebServletContextListener.getApplicationContext().getBean("applicationMBean");

        if (accion == applicationMBean.getLista()) {
            sbTitulo.append(UtilCore.Internacionalizacion.getMensajeInternacional("general.titulo.lista"));
        } else if (accion == applicationMBean.getNuevo()) {
            sbTitulo.append(UtilCore.Internacionalizacion.getMensajeInternacional("general.titulo.nuevo"));
        } else if (accion == applicationMBean.getEditar()) {
            sbTitulo.append(UtilCore.Internacionalizacion.getMensajeInternacional("general.titulo.editar"));
        } else if (accion == applicationMBean.getVer()) {
            sbTitulo.append(UtilCore.Internacionalizacion.getMensajeInternacional("general.titulo.ver"));
        }
        sbTitulo.append(" ");
        sbTitulo.append(UtilCore.Internacionalizacion.getMensajeInternacional(keyEntidad));

        retorno = sbTitulo.toString();

        return retorno;
    }

    public SelectItem[] siTiposParametro() {
        SelectItem[] si = new SelectItem[2];
        si[0] = new SelectItem("EMPRESA", "EMPRESA");
        si[1] = new SelectItem("SISTEMA", "SISTEMA");
        return si;
    }

    public String viewReportePdf(HashMap hmParametros, String reporte, String nombreArchivo) throws FileNotFoundException, JRException, IOException, SQLException {
        InputStream ie = null;
        Connection c = null;
        try {
            ApplicationMBean applicationMBean = (ApplicationMBean) WebServletContextListener.getApplicationContext().getBean("applicationMBean");
            File file = new File(applicationMBean.getRutaArchivos());
            ie = new FileInputStream(new File(file.getCanonicalPath(), "jaspers" + file.separator + reporte + ".jasper"));
            c = applicationMBean.obtenerConexionDataBase();
            if (c != null) {
                logger.info("P_DIRECTORIO_REPORTES: " + file.getCanonicalPath());
                hmParametros.put("P_DIRECTORIO_PRINCIPAL", file.getCanonicalPath() + file.separator);
                hmParametros.put("P_LOGO", "ERP.png");
                hmParametros.put(JRParameter.REPORT_LOCALE, new Locale("es_PE"));
                hmParametros.put(JRParameter.REPORT_TIME_ZONE, applicationMBean.getTimeZone());
                JasperPrint jasperPrint = JasperFillManager.fillReport(ie, hmParametros, c);
                logger.info("el jasperProcesado: " + jasperPrint.toString());
                byte[] bytes = JasperExportManager.exportReportToPdf(jasperPrint);
                FacesContext context = FacesContext.getCurrentInstance();
                HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
                response.addHeader("Content-disposition",
                        "attachment;filename=" + nombreArchivo);
                response.setContentLength(bytes.length);
                response.getOutputStream().write(bytes);
                response.setContentType("application/pdf");
                context.responseComplete();
            } else {
                logger.error("NO SE PUEDO EJECUTAR LA IMPRESION LA CONEXION ES NULA");
            }

            return null;
        } catch (JRException ex) {
            logger.error("Error al rellenar el reporte " + ex.getMessage());
            logger.error(ex);
            showError(ex.getMessage());
        } catch (IOException ex) {
            logger.error("Error al leer el jasper " + ex.getMessage());
            logger.error(ex);
            showError(ex.getMessage());
        } catch (Throwable ex) {
            logger.error("Otros errores con el jasper " + ex.getMessage());
            logger.error(ex);
            showError(ex.getMessage());
        } finally {
            try {
                if (c != null) {
                    c.close();
                }
                if (ie != null) {
                    ie.close();
                }
            } catch (IOException ex) {
                logger.error(ex);
                showError(ex.getMessage());
            }
            return null;
        }

    }

    public int[] listaEnteros(int inicio, int fin) {
        int total = fin - inicio + 2;
        int[] arreglo = new int[total];
        arreglo[0] = -1;
        int indice = 1;
        for (int i = inicio; i <= fin; i++) {
            arreglo[indice++] = i;
        }
        return arreglo;
    }
    
    

    public SelectItem[] siMesesAnio(boolean addTodos) {
        int total = 12;
        SelectItem[] si = null;
        int indice = 0;
        if (addTodos) {
            si = new SelectItem[total + 1];
            int id = com.brain.core.common.ConstantesCore.ExpresionQuartzCodigos.TODOS;
            String label = com.brain.core.common.ConstantesCore.ExpresionQuartzEtiquetas.TODOS;
            si[indice++] = new SelectItem(id, label);
        } else {
            si = new SelectItem[total];
        }
        for (int i = 0; i < 12; i++) {
            si[indice++] = new SelectItem(i, com.brain.core.common.ConstantesCore.MESES_ANIO[i]);
        }
        return si;
    }

    public SelectItem[] siDiasSemana(boolean addTodos, boolean addIncognita) {
        int total = 7;

        if (addTodos) {
            total += 1;
        }
        if (addIncognita) {
            total += 1;
        }

        int indice = 0;
        SelectItem[] si = new SelectItem[total];
        if (addTodos) {
            int id = com.brain.core.common.ConstantesCore.ExpresionQuartzCodigos.TODOS;
            String label = com.brain.core.common.ConstantesCore.ExpresionQuartzEtiquetas.TODOS;
            si[indice++] = new SelectItem(id, label);
        }

        if (addIncognita) {
            int id = com.brain.core.common.ConstantesCore.ExpresionQuartzCodigos.INCOGNITA;
            String label = com.brain.core.common.ConstantesCore.ExpresionQuartzEtiquetas.INCOGNITA;
            si[indice++] = new SelectItem(id, label);
        }

        for (int i = 0; i < 7; i++) {
            si[indice++] = new SelectItem(i, com.brain.core.common.ConstantesCore.DIAS_SEMANA[i]);
        }

        return si;
    }

    public SelectItem[] siEnteros(int inicio, int fin, boolean addTodos, boolean addUltimo, boolean addPrimero, boolean addIncognita) {
        int total = fin - inicio + 1;
        if (addTodos) {
            total += 1;
        }
        if (addUltimo) {
            total += 1;
        }
        if (addPrimero) {
            total += 1;
        }
        if (addIncognita) {
            total += 1;
        }

        SelectItem[] si = new SelectItem[total];
        int indice = 0;
        if (addTodos) {
            int id = com.brain.core.common.ConstantesCore.ExpresionQuartzCodigos.TODOS;
            String label = com.brain.core.common.ConstantesCore.ExpresionQuartzEtiquetas.TODOS;
            si[indice++] = new SelectItem(id, label);
        }
        if (addUltimo) {
            int id = com.brain.core.common.ConstantesCore.ExpresionQuartzCodigos.ULTIMO;
            String label = com.brain.core.common.ConstantesCore.ExpresionQuartzEtiquetas.ULTIMO;
            si[indice++] = new SelectItem(id, label);
        }
        if (addPrimero) {
            int id = com.brain.core.common.ConstantesCore.ExpresionQuartzCodigos.PRIMERO;
            String label = com.brain.core.common.ConstantesCore.ExpresionQuartzEtiquetas.PRIMERO;
            si[indice++] = new SelectItem(id, label);
        }
        if (addIncognita) {
            int id = com.brain.core.common.ConstantesCore.ExpresionQuartzCodigos.INCOGNITA;
            String label = com.brain.core.common.ConstantesCore.ExpresionQuartzEtiquetas.INCOGNITA;
            si[indice++] = new SelectItem(id, label);
        }

        for (int i = inicio; i <= fin; i++) {
            si[indice++] = new SelectItem(i, i < 10 ? ("0" + i) : String.valueOf(i));
        }
        return si;
    }

    public void generarExcel(String cabecera, List listaExportar, String nombreArchivo) {
        try {
            ApplicationMBean applicationMBean = (ApplicationMBean) WebServletContextListener.getApplicationContext().getBean("applicationMBean");
            String ruta = applicationMBean.getRutaArchivos();
            File f = new File(ruta, nombreArchivo);
            f.createNewFile();
            WritableWorkbook workbook = Workbook.createWorkbook(f);

            WritableFont fuenteCelda = null;
            WritableCellFormat formatoCelda = null;
            WritableSheet sheet = workbook.createSheet("REPORTE", 0);

            // imprimiendo titulos
            fuenteCelda = new WritableFont(WritableFont.createFont("Calibri"), 8, WritableFont.BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.WHITE);
            formatoCelda = new WritableCellFormat(fuenteCelda);
            formatoCelda.setBackground(Colour.RED);
            formatoCelda.setAlignment(Alignment.CENTRE);
            formatoCelda.setVerticalAlignment(VerticalAlignment.TOP);

            formatoCelda.setBorder(Border.ALL, BorderLineStyle.NONE);

            StringTokenizer cabecera_array = new StringTokenizer(cabecera, "|");
            int columnas = 0;
            while (cabecera_array.hasMoreTokens()) {
                Label label;
                label = new Label(columnas, 0, cabecera_array.nextToken(), formatoCelda);
                sheet.addCell(label);
                columnas++;
            }

            CellView cv = new CellView();
            // Anchos de columnas
            for (int j = 0; j < columnas; j++) {
                cv = sheet.getColumnView(j);
                cv.setAutosize(true);
                sheet.setColumnView(j, cv);
            }

            fuenteCelda = new WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK);
            formatoCelda = new WritableCellFormat(fuenteCelda);
            formatoCelda.setBackground(Colour.WHITE);
            formatoCelda.setAlignment(Alignment.GENERAL);
            formatoCelda.setBorder(Border.ALL, BorderLineStyle.THIN);

            int fila = 1;
            for (Iterator iter = listaExportar.iterator(); iter.hasNext();) {
                String registro = (String) iter.next();
                StringTokenizer registro_array = new StringTokenizer(registro, "|");
                int columnas_registro = 0;
                while (registro_array.hasMoreTokens()) {
                    Label label;
                    label = new Label(columnas_registro, fila, registro_array.nextToken(), formatoCelda);
                    sheet.addCell(label);
                    columnas_registro++;
                }

                fila++;
            }
            workbook.write();
            workbook.close();
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public void viewArchivo(String archivo) {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", "attachment; filename=\"" + archivo + "\"");
        ApplicationMBean applicationMBean = (ApplicationMBean) WebServletContextListener.getApplicationContext().getBean("applicationMBean");
        byte[] buf = new byte[1024];
        try {
            File file = new File(applicationMBean.getRutaArchivos() + archivo);
            long length = file.length();
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
            ServletOutputStream out = response.getOutputStream();
            response.setContentLength((int) length);
            while ((in != null) && ((length = in.read(buf)) != -1)) {
                out.write(buf, 0, (int) length);
            }
            in.close();
            out.close();
        } catch (Exception exc) {
            logger.error(exc);
        }
    }

    public void showMessage(String msjResumen) {
        FacesMessage msj = new FacesMessage(FacesMessage.SEVERITY_INFO, msjResumen, null);
        FacesContext.getCurrentInstance().addMessage(null, msj);
    }

    public void showMessage(String msjResumen, String msjDetalle) {
        FacesMessage msj = new FacesMessage(FacesMessage.SEVERITY_INFO, msjResumen, msjDetalle);
        FacesContext.getCurrentInstance().addMessage(null, msj);
    }

    public void showWarning(String msjResumen) {
        FacesMessage msj = new FacesMessage(FacesMessage.SEVERITY_WARN, msjResumen, null);
        FacesContext.getCurrentInstance().addMessage(null, msj);
    }

    public void showWarning(String msjResumen, String msjDetalle) {
        FacesMessage msj = new FacesMessage(FacesMessage.SEVERITY_WARN, msjResumen, msjDetalle);
        FacesContext.getCurrentInstance().addMessage(null, msj);
    }

    public void showError(String msjResumen) {
        FacesMessage msj = new FacesMessage(FacesMessage.SEVERITY_ERROR, msjResumen, null);
        FacesContext.getCurrentInstance().addMessage(null, msj);
    }

    public void showError(String msjResumen, String msjDetalle) {
        FacesMessage msj = new FacesMessage(FacesMessage.SEVERITY_ERROR, msjResumen, msjDetalle);
        FacesContext.getCurrentInstance().addMessage(null, msj);
    }

    public void showFatal(String msjResumen) {
        FacesMessage msj = new FacesMessage(FacesMessage.SEVERITY_FATAL, msjResumen, null);
        FacesContext.getCurrentInstance().addMessage(null, msj);
    }

    public void showFatal(String msjResumen, String msjDetalle) {
        FacesMessage msj = new FacesMessage(FacesMessage.SEVERITY_FATAL, msjResumen, msjDetalle);
        FacesContext.getCurrentInstance().addMessage(null, msj);
    }

    public static void main(String[] a) {
        EnviadorMail("ronald.chang.jbiss@gmail.com", "Prueba", "Cuerpo del email");
    }

    public static void EnviadorMail(String mailReceptor, String asunto,
            String cuerpo) {

        String miCorreo = "sgc.cmac.cusco@gmail.com";
        String miPassword = "sgc_2013";
        String servidorSMTP = "smtp.gmail.com";
        String puertoEnvio = "465";

        Properties props = new Properties();
        props.put("mail.smtp.user", miCorreo);
        props.put("mail.smtp.host", servidorSMTP);
        props.put("mail.smtp.port", puertoEnvio);
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.socketFactory.port", puertoEnvio);
        props.put("mail.smtp.socketFactory.class",
                "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.socketFactory.fallback", "false");

        SecurityManager security = System.getSecurityManager();

        try {
            Authenticator auth = new javax.mail.Authenticator() {
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("sgc.cmac.cusco@gmail.com", "sgc_2013");
                }
            };

            Session session = Session.getInstance(props, auth);
            // session.setDebug(true);

            MimeMessage msg = new MimeMessage(session);
            msg.setText(cuerpo);
            msg.setSubject(asunto);
            msg.setFrom(new InternetAddress(miCorreo));
            msg.addRecipient(Message.RecipientType.TO, new InternetAddress(
                    mailReceptor));
            Transport.send(msg);
        } catch (Exception mex) {
            mex.printStackTrace();
        }

    }
    
    public ParametroDto obtenerParametroPorID(Long parametro) throws DAOException{
        return parametroManager.obtenerPorId(parametro);
    }

    public List<EmpresaDto> obtenerEmpresasActivasComboUbigeoPadre() {
        EmpresaManager manager = (EmpresaManager) WebServletContextListener.getApplicationContext().getBean("empresaManager");
        List<EmpresaDto> l = new ArrayList<EmpresaDto>();
        try {
            EmpresaDto dto = new EmpresaDto();
            dto.setId(0L);
            dto.setDescripcion("UBIGEO PADRE");
            l.add(dto);
            l.addAll(manager.obtenerTodos());
        } catch (DAOException ex) {
            logger.error(ex);
        }

        return l;
    }

    public List<EmpresaDto> obtenerEmpresasActivasCombo() {
        EmpresaManager manager = (EmpresaManager) WebServletContextListener.getApplicationContext().getBean("empresaManager");
        List<EmpresaDto> l = new ArrayList<EmpresaDto>();
        try {
            l.addAll(manager.obtenerTodos());
        } catch (DAOException ex) {
            logger.error(ex);
        }

        return l;
    }

    public SelectItem[] siTiposModulos() {
        SelectItem[] si = new SelectItem[4];
        si[0] = new SelectItem("", "NINGUNO");
        si[1] = new SelectItem("SEGU", "SEGU");
        si[2] = new SelectItem("CORE", "CORE");
        si[3] = new SelectItem("CONF", "CONF");
        return si;
    }

    public SelectItem[] siTipoValoracion() {
        SelectItem[] si = new SelectItem[3];
        si[0] = new SelectItem("A", "ALTA");
        si[1] = new SelectItem("M", "MEDIA");
        si[2] = new SelectItem("B", "BAJA");
        return si;
    }

    public SelectItem[] siTipoClFacturacion() {
        SelectItem[] si = new SelectItem[4];
        si[0] = new SelectItem("D", "DESPUES DE ENTREGADO");
        si[1] = new SelectItem("I", "INMEDIATO");
        si[2] = new SelectItem("N", "NO FACTURAR");
        si[3] = new SelectItem("P", "PEDIDO COMPLETAMENTE ENTREGADO");
        return si;
    }

    public List<ParametroDto> obtenerParametrosActivosPorCatalogoSistema(final Long catalogo) {
        ParametroManager manager = (ParametroManager) WebServletContextListener.getApplicationContext().getBean("parametroManager");
        try {
            return manager.obtenerParametrosActivosPorCatalogoSistema(catalogo);
        } catch (DAOException ex) {
            logger.error(ex);
            return null;
        }
    }
    
    public static ParametroDto obtenerParametroPorId(Long id) {

        ParametroManager manager = (ParametroManager) WebServletContextListener.getApplicationContext().getBean("parametroManager");
        try {
            return manager.obtenerPorId(id);
        } catch (DAOException ex) {
            logger.error(ex);
            return null;
        }
    }

    public List<ParametroDto> obtenerParametrosActivosPorCatalogoExceptoAlgunos(final Long catalogo, Long... excepciones) {
        ParametroManager manager = (ParametroManager) WebServletContextListener.getApplicationContext().getBean("parametroManager");
        List<ParametroDto> l = new ArrayList<ParametroDto>();
        List<ParametroDto> lAux = new ArrayList<ParametroDto>();
        try {
            l.addAll(manager.obtenerParametrosActivosPorCatalogoSistema(catalogo));
        } catch (DAOException ex) {
            logger.error(ex);
        }

        for (ParametroDto x : l) {
            for (Long e : excepciones) {
                if (!x.getId().equals(e)) {
                    lAux.add(x);
                }
            }

        }
        return lAux;
    }

    public List<ParametroDto> addParametroaListaParametroPorCatalogo(final List<ParametroDto> l, Long... add) {
        try {
            ParametroManager manager = (ParametroManager) WebServletContextListener.getApplicationContext().getBean("parametroManager");
            for (Long e : add) {
                l.add(manager.obtenerPorId(e));
            }
        } catch (DAOException ex) {
            logger.error(ex);
        }


        return l;
    }

    public List<ParametroDto> obtenerParametrosActivosPorCatalogoSistemaAdd(final Long catalogo, Long... add) {
        ParametroManager manager = (ParametroManager) WebServletContextListener.getApplicationContext().getBean("parametroManager");
        List<ParametroDto> l = new ArrayList<ParametroDto>();
        try {
            for (Long x : add) {
                l.add(manager.obtenerPorId(x));
            }
            l.addAll(manager.obtenerParametrosActivosPorCatalogoSistema(catalogo));
        } catch (DAOException ex) {
            logger.error(ex);
        }

        return l;
    }

    public List<ParametroDto> obtenerParametrosActivosPorCatalogoSistemaFiltro(final Long catalogo) {
        ParametroManager manager = (ParametroManager) WebServletContextListener.getApplicationContext().getBean("parametroManager");
        List<ParametroDto> l = new ArrayList<ParametroDto>();
        try {
            ParametroDto dto = new ParametroDto();
            dto.setId(0L);
            dto.setDescripcion("*");
            l.add(dto);
            l.addAll(manager.obtenerParametrosActivosPorCatalogoSistema(catalogo));
        } catch (DAOException ex) {
            logger.error(ex);
            return null;
        }
        return l;
    }

    public static Logger getLogger() {
        return logger;
    }

    public static void setLogger(Logger logger) {
        RecursosManager.logger = logger;
    }

    public ParametroManager getParametroManager() {
        return parametroManager;
    }

    public void setParametroManager(ParametroManager parametroManager) {
        this.parametroManager = parametroManager;
    }
}
